package com.xhj.mybatis.plugin;

import com.xhj.mybatis.mapping.BoundSql;
import com.xhj.mybatis.mapping.ParameterMapping;
import com.xhj.mybatis.reflection.MetaObject;
import com.xhj.mybatis.session.Configuration;

import java.sql.PreparedStatement;
import java.util.*;

/**
 * ParameterObjectUtil
 *
 * @author XJks
 * @description 参数对象工具类，可视化参数对象的内容，辅助测试使用。
 */
public class InterceptorUtil {

    /**
     * 获取参数对象的简要视图信息
     *
     * @param boundSql      绑定的 SQL 对象，包含 SQL 语句和参数信息
     * @param configuration MyBatis 的全局配置对象
     * @return 参数对象的字符串表示
     */
    public static String getParameterObjectView(BoundSql boundSql, Configuration configuration) {
        // 获取 boundSql 中的参数对象
        Object parameterObject = boundSql.getParameterObject();
        // 如果参数对象为 null，则返回字符串 "null"
        if (parameterObject == null) return "null";

        // 获取 SQL 语句中的参数映射列表
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        // 如果参数映射列表为空，则直接返回参数对象的字符串表示
        if (parameterMappings == null || parameterMappings.isEmpty()) return String.valueOf(parameterObject);
        // 创建一个 Map 来存储参数名称和值的对应关系
        Map<String, Object> map = new LinkedHashMap<>();
        /**
         * TODO:根据 {@link com.xhj.mybatis.scripting.defaults.DefaultParameterHandler#setParameters(PreparedStatement)} 方法中的逻辑来获取参数值，填充返回的试图对象 map。
         */
        if (parameterMappings != null) {
            for (int i = 0; i < parameterMappings.size(); i++) {
                // 获取第 i 个参数映射
                ParameterMapping parameterMapping = parameterMappings.get(i);
                // 最终要设置到 SQL 的参数值
                Object value;
                // 参数对应的属性名
                String propertyName = parameterMapping.getProperty();
                // 根据不同情况获取参数值
                if (boundSql.hasAdditionalParameter(propertyName)) {
                    // TODO:如果 boundSql 中有额外的参数，优先从 BoundSql 的附加参数中获取（如 foreach、bind 等动态参数）
                    value = boundSql.getAdditionalParameter(propertyName);
                } else if (parameterObject == null) {
                    // 如果参数对象为 null，则参数值为 null
                    value = null;
                } else if (configuration.getTypeHandlerRegistry().hasTypeHandler(parameterObject.getClass())) {
                    // 如果参数对象有对应的 TypeHandler，直接使用参数对象本身
                    value = parameterObject;
                } else {
                    // 否则通过反射从参数对象中获取对应属性的值
                    MetaObject metaObject = configuration.newMetaObject(parameterObject);
                    value = metaObject.getValue(propertyName);
                }
                map.put(propertyName, value);
            }
        }
        return map.toString();
    }

    /**
     * 获取结果的简要视图信息
     *
     * @param result 结果对象
     * @return 结果的字符串表示
     */
    public static String getResultView(Object result) {
        if (result == null) return "null";
        if (result instanceof Collection) return "Collection(size=" + ((Collection<?>) result).size() + ")";
        return result.getClass().getSimpleName();
    }
}
